/**
 * ParameterCalculator - 参数计算工具类
 * 
 * 统一的参数计算方法，用于TDC分析和全图处理
 * 提供一致的算法保证计算结果的统一性
 */
class ParameterCalculator {
  constructor(timeArray = null) {
    this.timeArray = timeArray;
  }

  /**
   * 设置时间数组
   * @param {Array} timeArray 时间数组
   */
  setTimeArray(timeArray) {
    this.timeArray = timeArray;
  }

  /**
   * 平滑处理函数 - 移动平均滤波
   * @param {Array} curve 原始曲线数据
   * @param {number} windowSize 窗口大小，默认3
   * @returns {Array} 平滑后的曲线
   */
  smoothTimeCurve(curve, windowSize = 3) {
    if (curve.length <= windowSize) {
      // 对于小数组，直接复制
      const result = new Array(curve.length);
      for (let i = 0; i < curve.length; i++) {
        result[i] = curve[i];
      }
      return result;
    }
    
    const smoothed = new Array(curve.length);
    const halfWindow = Math.floor(windowSize / 2);
    
    for (let i = 0; i < curve.length; i++) {
      let sum = 0;
      let count = 0;
      
      const startJ = Math.max(0, i - halfWindow);
      const endJ = Math.min(curve.length - 1, i + halfWindow);
      
      for (let j = startJ; j <= endJ; j++) {
        sum += curve[j];
        count++;
      }
      
      smoothed[i] = sum / count;
    }
    
    return smoothed;
  }

  /**
   * 预处理时间曲线 - 平滑 + 基线校正
   * @param {Array} timeCurve 原始时间曲线
   * @returns {Object} 包含处理结果的对象
   */
  preprocessTimeCurve(timeCurve) {
    // 平滑处理
    const smoothedCurve = this.smoothTimeCurve(timeCurve);
    
    // 基线校正 - 使用第一帧作为基线
    const baselineValue = smoothedCurve[0];
    const correctedCurve = new Array(smoothedCurve.length);
    
    for (let i = 0; i < smoothedCurve.length; i++) {
      correctedCurve[i] = Math.max(0, smoothedCurve[i] - baselineValue);
    }
    
    return {
      smoothedCurve,
      correctedCurve,
      baselineValue
    };
  }

  /**
   * 计算峰值和峰值位置
   * @param {Array} correctedCurve 基线校正后的曲线
   * @returns {Object} 包含峰值和峰值位置的对象
   */
  calculatePeak(correctedCurve) {
    let peakValue = -Infinity;
    let peakIndex = 0;
    
    for (let i = 0; i < correctedCurve.length; i++) {
      if (correctedCurve[i] > peakValue) {
        peakValue = correctedCurve[i];
        peakIndex = i;
      }
    }
    
    return { peakValue, peakIndex };
  }

  /**
   * 计算平均通过时间 (MTT) - Mean Transit Time
   * @param {Array} correctedCurve 基线校正后的曲线
   * @param {Array} timeData 时间数据，可选，使用this.timeArray
   * @returns {number} MTT值
   */
  calculateMTT(correctedCurve, timeData = null) {
    const timeArray = timeData || this.timeArray;
    if (!timeArray) {
      console.warn('MTT计算需要时间数组');
      return 0;
    }

    let weightedSum = 0;
    let totalSignal = 0;
    
    for (let i = 0; i < correctedCurve.length; i++) {
      const realTime = timeArray[i];
      const signal = correctedCurve[i];
      if (signal > 0) {
        weightedSum += realTime * signal;
        totalSignal += signal;
      }
    }
    
    return totalSignal > 0 ? weightedSum / totalSignal : 0;
  }

  /**
   * 计算曲线下面积 (AUC) - Area Under Curve
   * @param {Array} correctedCurve 基线校正后的曲线
   * @param {Array} timeData 时间数据，可选，使用this.timeArray
   * @returns {number} AUC值
   */
  calculateAUC(correctedCurve, timeData = null) {
    const timeArray = timeData || this.timeArray;
    if (!timeArray) {
      console.warn('AUC计算需要时间数组');
      return 0;
    }

    let auc = 0;
    
    for (let i = 1; i < correctedCurve.length; i++) {
      const timeInterval = timeArray[i] - timeArray[i-1];
      const trapezoidArea = (correctedCurve[i] + correctedCurve[i-1]) * timeInterval * 0.5;
      auc += trapezoidArea;
    }
    
    return auc;
  }

  /**
   * 计算脑血流量 (CBF) - Cerebral Blood Flow
   * @param {Array} correctedCurve 基线校正后的曲线
   * @param {Array} timeData 时间数据，可选，使用this.timeArray
   * @returns {number} CBF值 (ml/100g/min)
   */
  calculateCBF(correctedCurve, timeData = null) {
    // 计算峰值和MTT
    const { peakValue } = this.calculatePeak(correctedCurve);
    const mtt = this.calculateMTT(correctedCurve, timeData);
    
    // CBF = Peak / MTT * 60 (转换为每分钟)
    const cbf = mtt > 0 ? (peakValue / mtt) * 60 : 0;
    return cbf;
  }

  /**
   * 计算脑血容量 (CBV) - Cerebral Blood Volume
   * @param {Array} correctedCurve 基线校正后的曲线
   * @returns {number} CBV值 (ml/100g)
   */
  calculateCBV(correctedCurve) {
    // 计算峰值
    const { peakValue } = this.calculatePeak(correctedCurve);
    
    // 简化的相对CBV计算
    const cbv = peakValue * 0.1;
    return cbv;
  }

  /**
   * 计算基本统计信息 (Peak, TTP, AUC)
   * @param {Array} signalData 信号数据
   * @param {Array} timeData 时间数据
   * @returns {Object} 包含peak, ttp, auc的统计信息
   */
  calculateBasicStatistics(signalData, timeData) {
    if (!signalData || signalData.length === 0) {
      return { peak: 0.0, ttp: 0.0, auc: 0.0 };
    }

    try {
      // 过滤有效数据
      const validSignals = signalData.filter(v => !isNaN(v) && isFinite(v));
      if (validSignals.length === 0) {
        return { peak: 0.0, ttp: 0.0, auc: 0.0 };
      }

      // 预处理时间曲线
      const { correctedCurve } = this.preprocessTimeCurve(signalData);
      
      // 计算峰值和峰值位置
      const { peakValue, peakIndex } = this.calculatePeak(correctedCurve);
      
      // 达峰时间 (TTP) - 使用真实时间
      const ttp = timeData[peakIndex] || 0.0;
      
      // 曲线下面积 (AUC)
      const auc = this.calculateAUC(correctedCurve, timeData);
      
      return {
        peak: parseFloat(peakValue.toFixed(1)),
        ttp: parseFloat(ttp.toFixed(2)),
        auc: parseFloat(auc.toFixed(1))
      };
    } catch (error) {
      console.error('基本统计计算失败:', error);
      return { peak: 0.0, ttp: 0.0, auc: 0.0 };
    }
  }

  /**
   * 计算扩展参数 (MTT, CBF, CBV)
   * @param {Array} signalData 信号数据
   * @param {Array} timeData 时间数据
   * @returns {Object} 包含mtt, cbf, cbv的扩展参数
   */
  calculateExtendedParameters(signalData, timeData) {
    if (!signalData || signalData.length === 0) {
      return { mtt: 0.0, cbf: 0.0, cbv: 0.0 };
    }

    try {
      // 预处理时间曲线
      const { correctedCurve } = this.preprocessTimeCurve(signalData);
      
      // 计算MTT
      const mtt = this.calculateMTT(correctedCurve, timeData);
      
      // 计算CBF
      const cbf = this.calculateCBF(correctedCurve, timeData);
      
      // 计算CBV
      const cbv = this.calculateCBV(correctedCurve);
      
      return {
        mtt: parseFloat(mtt.toFixed(2)),
        cbf: parseFloat(cbf.toFixed(2)),
        cbv: parseFloat(cbv.toFixed(2))
      };
    } catch (error) {
      console.error('扩展参数计算失败:', error);
      return { mtt: 0.0, cbf: 0.0, cbv: 0.0 };
    }
  }

  /**
   * 计算所有参数 (完整的参数集合)
   * @param {Array} signalData 信号数据
   * @param {Array} timeData 时间数据
   * @returns {Object} 包含所有参数的对象
   */
  calculateAllParameters(signalData, timeData) {
    const basicStats = this.calculateBasicStatistics(signalData, timeData);
    const extendedParams = this.calculateExtendedParameters(signalData, timeData);

    return {
      ...basicStats,
      ...extendedParams
    };
  }

  /**
   * 计算平均HU值 (Hounsfield Unit)
   * @param {Array} signalData 信号数据
   * @returns {number} 平均HU值
   */
  calculateHU(signalData) {
    if (!signalData || signalData.length === 0) return 0.0;
    
    try {
      const validSignals = signalData.filter(v => !isNaN(v) && isFinite(v));
      if (validSignals.length === 0) return 0.0;
      
      const average = validSignals.reduce((sum, val) => sum + val, 0) / validSignals.length;
      return parseFloat(average.toFixed(1));
    } catch (error) {
      console.error('HU计算失败:', error);
      return 0.0;
    }
  }

  /**
   * 为ImageProcessor提供像素级别的时间曲线提取
   * @param {Array} pixelDataArray 像素数据数组
   * @param {number} pixelIndex 像素索引
   * @returns {Array} 时间曲线
   */
  static extractTimeCurve(pixelDataArray, pixelIndex) {
    const timeCurve = [];
    const numFrames = pixelDataArray.length;
    
    for (let timeIndex = 0; timeIndex < numFrames; timeIndex++) {
      timeCurve.push(pixelDataArray[timeIndex].data[pixelIndex]);
    }
    
    return timeCurve;
  }

  /**
   * 获取数据的最小值和最大值
   * @param {Array} data 数据数组
   * @returns {Object} 包含min和max的对象
   */
  static getMinMax(data) {
    let min = Infinity;
    let max = -Infinity;
    
    for (let i = 0; i < data.length; i++) {
      const value = data[i];
      if (value < min) min = value;
      if (value > max) max = value;
    }
    
    return { min, max };
  }

  /**
   * 计算最大斜率 - Maximum Slope (用于最大斜率法)
   * @param {Array} timeCurve 时间密度曲线
   * @param {Array} timeData 时间数据
   * @returns {Object} 包含最大斜率值和位置的对象
   */
  calculateMaximumSlope(timeCurve, timeData = null) {
    const timeArray = timeData || this.timeArray;
    if (!timeArray || timeCurve.length < 3) {
      return { maxSlope: 0, slopeIndex: 0, slopeTime: 0 };
    }

    let maxSlope = 0;
    let slopeIndex = 0;
    let slopeTime = 0;

    // 计算相邻点之间的斜率
    for (let i = 1; i < timeCurve.length - 1; i++) {
      const deltaY = timeCurve[i + 1] - timeCurve[i - 1];
      const deltaT = timeArray[i + 1] - timeArray[i - 1];
      
      if (deltaT > 0) {
        const slope = deltaY / deltaT;
        if (slope > maxSlope) {
          maxSlope = slope;
          slopeIndex = i;
          slopeTime = timeArray[i];
        }
      }
    }

    return { maxSlope, slopeIndex, slopeTime };
  }

  /**
   * 计算基于最大斜率法的所有参数
   * @param {Array} tissueCurve 组织时间密度曲线
   * @param {Array} arterialCurve 动脉输入函数
   * @param {Array} timeData 时间数据
   * @returns {Object} 包含所有血流参数的对象
   */
  calculateMaximumSlopeParameters(tissueCurve, arterialCurve, timeData = null) {
    const timeArray = timeData || this.timeArray;
    
    // 预处理曲线 - 基线校正
    const { correctedCurve: correctedTissue } = this.preprocessTimeCurve(tissueCurve);
    const { correctedCurve: correctedArterial } = this.preprocessTimeCurve(arterialCurve);
    
    // 计算组织和动脉的最大斜率
    const tissueMaxSlope = this.calculateMaximumSlope(correctedTissue, timeArray);
    
    // 计算组织和动脉的峰值
    const tissuePeak = this.calculatePeak(correctedTissue);
    const arterialPeak = this.calculatePeak(correctedArterial);
    
    // CBF = TDC的最大斜率 / 动脉点的最大增强
    const cbf = arterialPeak.peakValue > 0 ? 
      (tissueMaxSlope.maxSlope / arterialPeak.peakValue) : 0;
    
    // CBV = 最大组织增强 / 最大动脉输入增强
    const cbv = arterialPeak.peakValue > 0 ? 
      (tissuePeak.peakValue / arterialPeak.peakValue) : 0;
    
    // MTT = CBV / CBF (中心容积定理)
    const mtt = cbf > 0 ? (cbv / cbf) : 0;
    
    // TTP = 组织达峰时间
    const ttp = timeArray && timeArray[tissuePeak.peakIndex] ? 
      timeArray[tissuePeak.peakIndex] : 0;
    
    // AUC = 组织曲线下面积
    const auc = this.calculateAUC(correctedTissue, timeArray);
    
    // 峰值 = 组织最大增强
    const peak = tissuePeak.peakValue;
    
    return {
      // 所有基本参数
      peak: parseFloat(peak.toFixed(1)),
      ttp: parseFloat(ttp.toFixed(2)),
      auc: parseFloat(auc.toFixed(1)),
      ph: parseFloat(peak.toFixed(1)),  // PH与peak相同，但保持独立字段
      mtt: parseFloat(mtt.toFixed(2)),
      cbf: parseFloat(cbf.toFixed(2)),
      cbv: parseFloat(cbv.toFixed(2)),
      
      // 用于调试的额外信息
      tissueMaxSlope: tissueMaxSlope.maxSlope,
      tissuePeakValue: tissuePeak.peakValue,
      arterialPeakValue: arterialPeak.peakValue,
      tissueSlopeTime: tissueMaxSlope.slopeTime
    };
  }

  /**
   * 获取动脉输入函数
   * @param {Array} pixelDataArray 所有帧的像素数据
   * @param {Object} arterialInputPoint 动脉输入点坐标 {x, y}
   * @returns {Array} 动脉输入函数的时间密度曲线
   */
  static extractArterialInputFunction(pixelDataArray, arterialInputPoint) {
    if (!arterialInputPoint || !pixelDataArray || pixelDataArray.length === 0) {
      console.warn('无法提取动脉输入函数: 缺少动脉输入点或像素数据');
      return [];
    }

    const { x, y } = arterialInputPoint;
    const arterialCurve = [];
    
    console.log(`开始提取动脉输入函数，动脉输入点: (${x}, ${y})`);
    
    try {
      for (let frameIndex = 0; frameIndex < pixelDataArray.length; frameIndex++) {
        const frameData = pixelDataArray[frameIndex];
        // 修复字段名不匹配问题：使用 data 而不是 pixelData
        const { rows, columns, data: pixelData } = frameData;
        
        // 边界检查
        if (x < 0 || x >= columns || y < 0 || y >= rows) {
          console.warn(`动脉输入点 (${x}, ${y}) 超出图像边界 ${columns}x${rows}`);
          arterialCurve.push(0);
          continue;
        }
        
        const pixelIndex = y * columns + x;
        const pixelValue = pixelData[pixelIndex] || 0;
        arterialCurve.push(pixelValue);
        
        // 在前几帧打印调试信息
        if (frameIndex < 3) {
          console.log(`帧${frameIndex}: 像素索引=${pixelIndex}, 像素值=${pixelValue}, 图像尺寸=${columns}x${rows}`);
        }
      }
      
      console.log(`动脉输入函数提取完成: ${arterialCurve.length} 个时间点`);
      console.log(`动脉输入函数前5个值:`, arterialCurve.slice(0, 5));
      
      return arterialCurve;
    } catch (error) {
      console.error('提取动脉输入函数失败:', error);
      return [];
    }
  }
}

export default ParameterCalculator; 